//
//  MatrixTests.m
//  3DMathSDK
//
//  Created by admin on 16/7/5.
//  Copyright © 2016年 douyu. All rights reserved.
//

#import <XCTest/XCTest.h>
#import "Matrix.h"

@interface MatrixTests : XCTestCase

@end

@implementation MatrixTests

- (void)setUp {
    [super setUp];
    // Put setup code here. This method is called before the invocation of each test method in the class.
}

- (void)tearDown {
    // Put teardown code here. This method is called after the invocation of each test method in the class.
    [super tearDown];
}

- (void)testIsMatrixEqual
{
    Matrix matrix1 = MatrixMake(1, 2, (float[2]){1.f, 2.f});
    Matrix matrix2 = MatrixMake(1, 2, (float[2]){1.f, 2.f});
    Matrix matrix3 = MatrixMake(1, 2, (float[2]){3.f, 4.f});
    
    XCTAssert(isMatrixEqual(matrix1, matrix2) == true);
    XCTAssert(isMatrixEqual(matrix2, matrix3) == false);
}

- (void)testMatrixVector3Convert
{
    Vector3 vec1 = {1.f, 2.f, 3.f};
    Matrix mat1 = MatrixMake(3, 1, (float[3]){1.f, 2.f, 3.f});
    
    Matrix testMat1 = MatrixFromVector3(vec1);
    XCTAssert(isMatrixEqual(testMat1, mat1));
    
    Vector3 testvec1 = Vector3FromMatrix(mat1);
    XCTAssert(isVectorEqual(testvec1, vec1));
}

- (void)testMultiply {
    Matrix matrix1 = MatrixMake(3, 3, (float[9]){1.f, -5.f, 3.f, 0.f, -2.f, 6.f, 7.f, 2.f, -4.f});
    Matrix matrix2 = MatrixMake(3, 3, (float[9]){-8.f, 6.f, 1.f, 7.f, 0.f, -3.f, 2.f, 4.f, 5.f});
    
    Matrix result = MatrixMake(3, 3, (float[9]){-37.f, 18.f, 31.f, -2.f, 24.f, 36.f, -50.f, 26.f, -19.f});
    
    Matrix test = multiply(matrix1, matrix2);
    XCTAssert(isMatrixEqual(test, result));
}

- (void)testTranspose
{
    Matrix mat = MatrixMake(4, 3, (float[12]){1.f, 2.f, 3.f, 4.f, 5.f, 6.f, 7.f, 8.f, 9.f, 10.f, 11.f, 12.f});
    
    Matrix result = MatrixMake(3, 4, (float[12]){1.f, 4.f, 7.f, 10.f, 2.f, 5.f, 8.f, 11.f, 3.f, 6.f, 9.f, 12.f});
    
    Matrix test = transpose(mat);
    XCTAssert(isMatrixEqual(test, result));
    printMatrix(test);
}

// 角转换为弧度
float radians(float angle)
{
    return angle/180.f*M_PI;
}

- (void)testRotateVector3Matrix
{
    Vector3 vec = {99.f, -99.f, 99.f};
    vec = normalize(vec);
    float angle = radians(-5);
    Matrix test = rotateVector3Matrix(vec, angle);
    printMatrix(test);
}

- (void)testScaleVector3Matrix
{
    Vector3 vec = {99.f, -99.f, 99.f};
    vec = normalize(vec);
    Matrix test = scaleVector3Matrix(vec, 5);
    printMatrix(test);
}

- (void)testDeterminant
{
    Matrix matrix1 = MatrixMake(2, 2, (float[4]){2, 1, -1, 2});
    float f1 = determinant(matrix1);
    XCTAssert(f1==5);
    
    Matrix matrix2 = MatrixMake(3, 3, (float[9]){3, -2, 0, 1, 4, -3, -1, 0, 2});
    float f2 = determinant(matrix2);
    XCTAssert(f2==22);
}

- (void)testCofactor
{
    Matrix mat1 = MatrixMake(3, 3, (float[9]){-4, -3, 3, 0, 2, -2, 1, 4, -1});
    
    float test11 = cofactor(mat1, 1, 1);
    XCTAssert(test11 == 6);
    
    float test33 = cofactor(mat1, 3, 3);
    XCTAssert(test33 == -8);
}

- (void)testAdjointMatrix
{
    Matrix mat1 = MatrixMake(3, 3, (float[9]){-4, -3, 3, 0, 2, -2, 1, 4, -1});
    Matrix result = MatrixMake(3, 3, (float[9]){6, 9, 0, -2, 1, -8, -2, 13, -8});
    Matrix test = adjointMatrix(mat1);
    printMatrix(test);
    XCTAssert(isMatrixEqual(test, result));
}

- (void)testInverseMatrix
{
    Matrix mat1 = MatrixMake(3, 3, (float[9]){-4, -3, 3, 0, 2, -2, 1, 4, -1});
    Matrix result = MatrixMake(3, 3, (float[9]){-1/4.f, -3/8.f, 0, 1/12.f, -1/24.f, 1/3.f, 1/12.f, -13/24.f, 1/3.f});
    Matrix test = inverseMatrix(mat1);
    printMatrix(test);
    XCTAssert(isMatrixEqual(test, result));
}

- (void)testIsIdentityMatrix
{
    Matrix mat1 = MatrixMake(2, 2, (float[4]){1,0,0,1});
    Matrix mat2 = MatrixMake(2, 3, (float[6]){1,2,3,4,5,6});
    Matrix mat3 = MatrixMake(3, 3, (float[9]){1,0,0,0,1,0,0,0,1});
    Matrix mat4 = MatrixMake(3, 3, (float[9]){1,0,0,0,1,0,0,1,1});
    Matrix mat5 = MatrixMake(3, 3, (float[9]){1,0,0,0,1,0,0,0,2});
    
    XCTAssert(isIdentityMatrix(mat1) == true);
    XCTAssert(isIdentityMatrix(mat2) == false);
    XCTAssert(isIdentityMatrix(mat3) == true);
    XCTAssert(isIdentityMatrix(mat4) == false);
    XCTAssert(isIdentityMatrix(mat5) == false);
}

- (void)testIsOrthogonalMatrix
{
    Matrix mat1 = MatrixMake(3, 3, (float[9]){-0.1495, -0.1986, 0.9685, -0.8256, 0.5640, 0.0117, -0.5439, -0.8015, 0.2482});
    Matrix mat2 = MatrixMake(2, 2, (float[4]){1,0,0,1});

    XCTAssert(isOrthogonalMatrix(mat1) == false);
    XCTAssert(isOrthogonalMatrix(mat2) == true);
}

@end
